#include <amdgpumonitor.h>
#include <QProcess>
#include <fstream>
#include <string>
#include <filesystem>
#include <tuple>
#include <cmath>

AMDGpuMonitor::AMDGpuMonitor()
{
    find_amdgpu_path();
}

void AMDGpuMonitor::find_amdgpu_path()
{
    gpu_dev_path.clear();

    for (const auto& entry : std::filesystem::directory_iterator("/sys/class/drm"))
    {
            const std::string card_name = entry.path().filename();
            if (card_name.find("card") == 0)
            {   // 检查是否是card设备
                std::string vendor_path = entry.path().string() + "/device/vendor";
                std::ifstream vendor_file(vendor_path);
                if (vendor_file.is_open())
                {
                    std::string vendor_id;
                    vendor_file >> vendor_id;
                    if (vendor_id == "0x1002")
                    {   // AMD的厂商ID
                        gpu_dev_path = entry.path().string() + "/device";
                        break;
                    }
                }
            }
    }
}




std::optional<double> AMDGpuMonitor::getGpuCoreUsage()
{
    const std::string usage_file_path = gpu_dev_path + "/gpu_busy_percent";
    std::ifstream file(usage_file_path);
    if (!file.is_open()) {
        return std::nullopt;
    }

    double usage;
    file >> usage;

    if (file.fail() || usage < 0.0 || usage > 100.0 || std::isnan(usage)) {
        return std::nullopt;
    }

    return usage;
}

std::optional<double> AMDGpuMonitor::getGpuMemUsage()
{
    double vram_total = 0;
    double vram_used = 0;

    std::ifstream total_file(gpu_dev_path + "/mem_info_vram_total");
    if (!total_file.is_open() || !(total_file >> vram_total)) {
        return std::nullopt;
    }

    std::ifstream used_file(gpu_dev_path + "/mem_info_vram_used");
    if (!used_file.is_open() || !(used_file >> vram_used)) {
        return std::nullopt;
    }

    if (vram_total <= 0.0) {
        return std::nullopt;
    }

    double usage = (vram_used / vram_total) * 100.0;
    if (usage < 0.0 || usage > 100.0 || std::isnan(usage)) {
        return std::nullopt;
    }

    return usage;
}

std::optional<double> AMDGpuMonitor::getGpuCoreTemp()
{
    std::string hwmon_path = gpu_dev_path + "/hwmon";
    
    if (!std::filesystem::exists(hwmon_path)) {
        return std::nullopt;
    }
    
    // 按名称排序，确保一致性
    std::vector<std::string> hwmon_dirs;
    for (const auto& entry : std::filesystem::directory_iterator(hwmon_path)) {
        if (entry.is_directory()) {
            hwmon_dirs.push_back(entry.path().string());
        }
    }
    std::sort(hwmon_dirs.begin(), hwmon_dirs.end());
    
    // 尝试所有可能的温度文件
    std::vector<std::string> temp_files = {"temp1_input", "temp2_input", "temp3_input"};
    
    for (const auto& hwmon_dir : hwmon_dirs) {
        for (const auto& temp_file_name : temp_files) {
            std::string temp_file_path = hwmon_dir + "/" + temp_file_name;
            std::ifstream temp_file(temp_file_path);
            
            if (temp_file.is_open()) {
                long temp_millicelsius;
                temp_file >> temp_millicelsius;
                
                if (!temp_file.fail() && temp_millicelsius > 0 && temp_millicelsius < 150000) {
                    double temp_celsius = temp_millicelsius / 1000.0;
                    return temp_celsius;
                }
            }
        }
    }
    
    return std::nullopt;
}